﻿using System;
using System.Data;
using System.IO;
using System.Text;
using System.Web.Services.Protocols;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using DBConnect;

namespace TISS_Add_in
{
    public partial class uc_Demonstrativos : UserControl
    {
        #region Construtor
        
        public uc_Demonstrativos()
        {
            InitializeComponent();
            carregaTreeViewDemonstrativos();
        }

        #endregion

        #region Eventos
        /// <summary>
        /// Seleciona nó que foi clicado com o mouse.
        /// Essa função é necessária pois o clique com o botão direito não seleciona o nó.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tvSolicitacoes_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            tvSolicitacoes.SelectedNode = e.Node;
        }
        /// <summary>
        /// Verifica qual nó será expandido e, caso necessário, atualiza os nós dentro do nó em expansão.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tvSolicitacoes_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            tvSolicitacoes.SelectedNode = e.Node;

            TreeNodeContentsDemonstrativo nodeContents = (TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag;
            TreeNodeContentsDemonstrativo nodeContentsChild = (TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Nodes[0].Tag;
            switch (nodeContents.tipo_node)
            {
                case node_type.operadora:
                    break;
                case node_type.tipo_lote:
                    if (nodeContentsChild.loteCod == null)
                        carregaNodeTipoGuia(e.Node, nodeContents);
                    break;
                case node_type.lote:
                    if (nodeContentsChild.numeroGuiaPrestador == null)
                        carregaNodeLoteGuia(e.Node, nodeContents);
                    break;
                case node_type.guiaFaturamento:
                    break;
                case node_type.guiaSolicitacao:
                    break;
                case node_type.guiaExtensao:
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// Verifica se o Demonstrativo já foi solicitado (existe no BD).
        /// Abre guia exibindo o demonstrativo.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void abrirDemonstrativoDePagamentoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag).demonstrativoCod != null)
            { // Abre arquivo Temporário exibindo o Demonstrativo de Pagamento
                docTissDemonstrativo.ct_demonstrativoPagamento demonstrativo = (docTissDemonstrativo.ct_demonstrativoPagamento)DemonstrativoRetorno.BuscaDemonstrativoRetorno(TipoGuia.Demonstrativo_Pagamento, ((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag).demonstrativoCod ?? 0);

                string file = criaDemonstrativoPagamento(demonstrativo);

                AddinUtils.AbrirGuia(file);
            }
            else
            { // Solicita Demonstrativo de Pagamento antes de exibi-lo
                atualizarDemonstrativoDePagamentoToolStripMenuItem_Click(sender, e);
                abrirDemonstrativoDePagamentoToolStripMenuItem_Click(sender, e);
            }
        }
        /// <summary>
        /// Gera solicitacao de Demonstrativo de Pagamento e envia para o WebService.
        /// Armazena resposta do WebService no Banco de Dados e atualiza nó selecionado do TreeView
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void atualizarDemonstrativoDePagamentoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            stsProgressBar.Visible = true;
            stsStatusLabel.Text = "Atualizando Demonstrativo...";

            solicitaDemonstrativo((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag, TISS_Add_in.docTissDemonstrativo.st_tipoDemonstrativo.Item1);

            TreeNodeContentsDemonstrativo nodeContents = (TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag;
            TreeNodeContentsDemonstrativo nodeContentsParent = (TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Parent.Tag;

            carregaNodeTipoGuia(tvSolicitacoes.SelectedNode.Parent, nodeContentsParent);
            tvSolicitacoes.SelectedNode.Expand();

            for (int i = 0; i < tvSolicitacoes.SelectedNode.Nodes.Count; i++)
            {
                if (((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Nodes[i].Tag).loteCod == nodeContents.loteCod)
                {
                    tvSolicitacoes.SelectedNode = tvSolicitacoes.SelectedNode.Nodes[i];
                    break;
                }
            }

            stsProgressBar.Visible = false;
            stsStatusLabel.Text = "";
        }
        /// <summary>
        /// Verifica se o Demonstrativo já foi solicitado (existe no BD).
        /// Abre guia exibindo o demonstrativo.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void abrirAnaliseDeContaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag).demonstrativoCod != null)
            { // Abre arquivo Temporário exibindo o Demonstrativo de Pagamento
                docTissDemonstrativo.ct_demonstrativoAnaliseConta demonstrativo = (docTissDemonstrativo.ct_demonstrativoAnaliseConta)DemonstrativoRetorno.BuscaDemonstrativoRetorno(TipoGuia.Demonstrativo_Análise_Conta, ((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag).demonstrativoCod ?? 0);

                string file = criaDemonstrativoAnaliseConta(demonstrativo, ((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag).loteCod.ToString(), ((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag).numeroGuiaPrestador);

                AddinUtils.AbrirGuia(file);
            }
            else
            { // Solicita Demonstrativo de Pagamento antes de exibi-lo
                atualizarAnaliseDeContaToolStripMenuItem_Click(sender, e);
                abrirAnaliseDeContaToolStripMenuItem_Click(sender, e);
            }
        }
        /// <summary>
        /// Gera solicitacao de demonstrativo de Análise de Conta e envia para o WebService.
        /// Armazena resposta do WebService no Banco de Dados e atualiza nó selecionado do TreeView
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void atualizarAnaliseDeContaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            stsProgressBar.Visible = true;
            stsStatusLabel.Text = "Atualizando Demonstrativo...";

            solicitaDemonstrativo((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag, TISS_Add_in.docTissDemonstrativo.st_tipoDemonstrativo.Item2);

            TreeNodeContentsDemonstrativo nodeContents = (TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Tag;
            TreeNodeContentsDemonstrativo nodeContentsParent = (TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Parent.Tag;

            carregaNodeLoteGuia(tvSolicitacoes.SelectedNode.Parent, nodeContentsParent);
            tvSolicitacoes.SelectedNode.Expand();

            for (int i = 0; i < tvSolicitacoes.SelectedNode.Nodes.Count; i++)
            {
                if (((TreeNodeContentsDemonstrativo)tvSolicitacoes.SelectedNode.Nodes[i].Tag).numeroGuiaPrestador == nodeContents.numeroGuiaPrestador)
                {
                    tvSolicitacoes.SelectedNode = tvSolicitacoes.SelectedNode.Nodes[i];
                    break;
                }
            }

            stsProgressBar.Visible = false;
            stsStatusLabel.Text = "";
        }

        #endregion

        #region Métodos
        /// <summary>
        /// Carrega o TreeView com as operadoras ligadas ao Usuário
        /// </summary>
        private void carregaTreeViewDemonstrativos()
        {
            tvSolicitacoes.Nodes.Clear();
            DataTable dtOperadoraFiliada = DBConnect.CommandModConf.buscaOperadoraFiliadaURL(Globals.ThisAddIn.UsuarioID);

            //Existe alguma operadora?
            if (dtOperadoraFiliada.Rows.Count > 0)
            {
                foreach (DataRow drOperadora in dtOperadoraFiliada.Rows)
                {
                    URLWebServices URLs = new URLWebServices();
                    URLs.URLCancelaGuia = drOperadora["url_cancela"].ToString();
                    URLs.URLLoteGuias = drOperadora["url_lote"].ToString();
                    URLs.URLSolicitacaoDemonstrativoRetorno = drOperadora["url_demonstrativo"].ToString();
                    URLs.URLSolicitacaoProcedimento = drOperadora["url_procedimento"].ToString();
                    URLs.URLSolicitacaoStatusProtocolo = drOperadora["url_protocolo"].ToString();
                    URLs.URLSolicitacaoStatusAutorizacao = drOperadora["url_autorizacao"].ToString();

                    TreeNodeContentsDemonstrativo tnOperadora = new TreeNodeContentsDemonstrativo(drOperadora["regANS"].ToString(), URLs);

                    //Adiciona Operadora a um Node
                    TreeNode nodeOperadora = new TreeNode(drOperadora["nome"].ToString());
                    nodeOperadora.Tag = tnOperadora;
                    nodeOperadora.ImageIndex = 0;
                    nodeOperadora.SelectedImageIndex = 0;

                    //TODO: OV - Todos - todos os tipos de guia possuem demonstrativo? discutir
                    int[] tipos = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //tipos das guias que serão apresentadas no treeview
                    TipoGuia tipoGuia;
                    foreach (int tipo in tipos)
                    {
                        tipoGuia = (TipoGuia)tipo;

                        TreeNodeContentsDemonstrativo tnTipoGuia = new TreeNodeContentsDemonstrativo(tnOperadora.regANS, tnOperadora.URLs, tipoGuia);

                        TreeNode nodeTipoDemonstrativo = new TreeNode(tipoGuia.ToString());
                        nodeTipoDemonstrativo.Tag = tnTipoGuia;
                        nodeTipoDemonstrativo.ImageIndex = 1;
                        nodeTipoDemonstrativo.SelectedImageIndex = 1;

                        #region Lote Fake
                        //Os lotes reais serão carregados quando o usuário expandir o nó
                        TreeNode nodeLoteFake = new TreeNode();
                        nodeLoteFake.Tag = tnTipoGuia;

                        nodeTipoDemonstrativo.Nodes.Add(nodeLoteFake);

                        #endregion

                        nodeOperadora.Nodes.Add(nodeTipoDemonstrativo);
                    }
                    tvSolicitacoes.Nodes.Add(nodeOperadora);
                }
            }
        }
        /// <summary>
        /// Atualiza os Lotes do nó TipoGuia selecionado
        /// </summary>
        /// <param name="selectedNode"></param>
        /// <param name="nodeContents"></param>
        private void carregaNodeTipoGuia(TreeNode selectedNode, TreeNodeContentsDemonstrativo nodeContents)
        {
            selectedNode.Nodes.Clear();

            DataTable dtLotes = CommandLotes.selecionaLoteGuiasEnviados(Globals.ThisAddIn.UsuarioID, nodeContents.regANS, (int)nodeContents.tipoGuia, (int)TipoGuia.Demonstrativo_Pagamento);

            if (dtLotes.Rows.Count > 0)
            {
                foreach (DataRow drLote in dtLotes.Rows)
                {
                    long? demonstrativoCod = null;
                    if (drLote["demonstrativoCod"].ToString() != "")
                        demonstrativoCod = Convert.ToInt64(drLote["demonstrativoCod"]);

                    TreeNodeContentsDemonstrativo tnLote = new TreeNodeContentsDemonstrativo(nodeContents.regANS, nodeContents.URLs, nodeContents.tipoGuia,
                            Convert.ToInt64(drLote["ID"]), Convert.ToInt64(drLote["sequencialTransacaoLote"]), Convert.ToInt64(drLote["protocoloRecebimento"]), demonstrativoCod);

                    //Adiciona Lote ao node
                    TreeNode nodeLote = new TreeNode(drLote["numeroLote"].ToString());
                    nodeLote.Tag = tnLote;
                    nodeLote.ImageIndex = 2;
                    nodeLote.SelectedImageIndex = 2;
                    nodeLote.ContextMenuStrip = ctxPagamento;

                    #region Guia Fake
                    //As Guias reais serão carregados quando o usuário expandir o nó
                    TreeNode nodeGuiaFake = new TreeNode();
                    nodeGuiaFake.Tag = tnLote;

                    nodeLote.Nodes.Add(nodeGuiaFake);

                    #endregion

                    selectedNode.Nodes.Add(nodeLote);
                }
            }
        }
        /// <summary>
        /// Atualiza as Guias do nó Lote selecionado
        /// </summary>
        /// <param name="selectedNode"></param>
        /// <param name="nodeContents"></param>
        private void carregaNodeLoteGuia(TreeNode selectedNode, TreeNodeContentsDemonstrativo nodeContents)
        {
            selectedNode.Nodes.Clear();

            DataTable dtGuias = CommandGuias.buscaGuiasLote(nodeContents.loteCod ?? 0, Convert.ToInt64(TipoGuia.Demonstrativo_Análise_Conta));

            if (dtGuias.Rows.Count > 0)
            {
                foreach (DataRow drGuia in dtGuias.Rows)
                {
                    long? demCod = null;
                    if (drGuia["demonstrativoCod"].ToString() != "")
                        demCod = Convert.ToInt64(drGuia["demonstrativoCod"].ToString());

                    TreeNodeContentsDemonstrativo tnGuia = new TreeNodeContentsDemonstrativo(nodeContents.regANS, nodeContents.URLs, nodeContents.tipoGuia,
                            nodeContents.loteCod ?? 0, nodeContents.sequencialTransacao ?? 0, nodeContents.protocoloRecebimento ?? 0, demCod,
                            drGuia["numeroGuia"].ToString(), drGuia["numeroGuiaOperadora"].ToString(), drGuia["dataEmissao"].ToString());

                    //Adiciona Guia ao node
                    TreeNode nodeGuia = new TreeNode(Path.GetFileNameWithoutExtension(drGuia["local"].ToString()));
                    nodeGuia.Tag = tnGuia;
                    nodeGuia.ImageIndex = 3;
                    nodeGuia.SelectedImageIndex = 3;
                    nodeGuia.ContextMenuStrip = ctxAnaliseConta;

                    selectedNode.Nodes.Add(nodeGuia);
                }
            }
        }

        private void solicitaDemonstrativo(TreeNodeContentsDemonstrativo tnContents, TISS_Add_in.docTissDemonstrativo.st_tipoDemonstrativo tipoDemonstrativo)
        {
            if (!tnContents.URLs.URLSolicitacaoDemonstrativoRetorno.Equals(""))
            {
                if (AddinUtils.ConfiguraConexao(tnContents.URLs))
                {
                    docTissDemonstrativo.ws_solicitacaoDemonstrativoRetorno solicitacao =
                        DemonstrativoRetorno.GeraSolicitacaoDemonstrativo(Globals.ThisAddIn.UsuarioID, tnContents.regANS, tnContents.protocoloRecebimento ?? 0, tipoDemonstrativo);

                    if (solicitacao != null)
                    {
                        try
                        {
                            TipoGuia tipo = new TipoGuia();
                            switch (tipoDemonstrativo)
                            {
                                case TISS_Add_in.docTissDemonstrativo.st_tipoDemonstrativo.Item1:
                                    tipo = TipoGuia.Demonstrativo_Pagamento;
                                    break;
                                case TISS_Add_in.docTissDemonstrativo.st_tipoDemonstrativo.Item2:
                                    tipo = TipoGuia.Demonstrativo_Análise_Conta;
                                    break;
                                case TISS_Add_in.docTissDemonstrativo.st_tipoDemonstrativo.Item3:
                                    tipo = TipoGuia.Demonstrativo_Odontologia;
                                    break;
                                default:
                                    break;
                            }

                            DemonstrativoRetorno.RecebeDemonstrativoRetorno(
                                Globals.ThisAddIn.docTISSwsDemonstrativoRetorno.tissSolicitacaoDemonstrativoRetorno_Operation(solicitacao),
                                tipo, Globals.ThisAddIn.UsuarioID, tnContents.regANS, tnContents.loteCod ?? 0);
                        }
                        catch (SoapException spEx)
                        {
                            //MensagemTISS não foi enviada, apagar registro do Banco de Dados
                            Mensagem.mensagemTISS_remove(Convert.ToInt64(solicitacao.cabecalho.identificacaoTransacao.sequencialTransacao));
                            AddinUtils.ShowErrorMessageWS(spEx);
                        }
                    }
                    else
                    {
                        MessageBox.Show("Prestador não cadastrado na operadora!", "Demonstrativo não solicitado!", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                    }
                }
            }
            else
            {
                MessageBox.Show("A operadora não possui URL de WebService cadastrado para esta operação!", "Demonstrativo não solicitado!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
            }
        }

        private string criaDemonstrativoPagamento(docTissDemonstrativo.ct_demonstrativoPagamento demonstrativo)
        {
            string templatePath = AppDomain.CurrentDomain.BaseDirectory + "templates\\demonstrativoPagamento.docx";
            string filePath = Path.GetTempFileName();

            XmlSerializer xs = new XmlSerializer(typeof(docTissDemonstrativo.ct_demonstrativoPagamento), XMLUtils.ElementRootWithANSnamespace("demonstrativoPagamento"));
            MemoryStream memoryStream = new MemoryStream();
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.GetEncoding("ISO-8859-1"));

            xs.Serialize(xmlTextWriter, demonstrativo, XMLUtils.ANSnamespace());
            memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
            memoryStream.Position = 0;

            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(memoryStream);
            File.Copy(templatePath, filePath, true);

            XMLUtils.SubstituiCustomXmlPart(filePath, "demonstrativoPagamento", xDoc);

            return filePath;
        }

        private string criaDemonstrativoAnaliseConta(docTissDemonstrativo.ct_demonstrativoAnaliseConta demonstrativo, string numeroLote, string numeroGuiaPrestador)
        {
            docTissDemonstrativo.ct_demonstrativoAnaliseConta analiseConta = demonstrativo;

            docTissDemonstrativo.ct_dadosLote[] analiseLote = new TISS_Add_in.docTissDemonstrativo.ct_dadosLote[1];
            docTissDemonstrativo.ct_dadosGuia[] analiseGuia = new TISS_Add_in.docTissDemonstrativo.ct_dadosGuia[1];

            foreach (docTissDemonstrativo.ct_dadosLote dadosLote in demonstrativo.fatura.dadosFatura.lote)
            {
                if (dadosLote.numeroLote.ToString() == numeroLote)
                {
                    analiseLote[0] = dadosLote;

                    foreach (docTissDemonstrativo.ct_dadosGuia dadosGuia in dadosLote.guia)
                        if (dadosGuia.numeroGuiaPrestador == numeroGuiaPrestador)
                            analiseGuia[0] = dadosGuia;

                    analiseLote[0].guia = analiseGuia;
                }
            }

            if (analiseLote[0] != null)
            {
                analiseConta.fatura.dadosFatura.lote = analiseLote;

                string templatePath = AppDomain.CurrentDomain.BaseDirectory + "templates\\demonstrativoAnaliseConta.docx";
                string filePath = Path.GetTempFileName();

                XmlSerializer xs = new XmlSerializer(typeof(docTissDemonstrativo.ct_demonstrativoAnaliseConta), XMLUtils.ElementRootWithANSnamespace("demonstrativoAnaliseConta"));
                MemoryStream memoryStream = new MemoryStream();
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.GetEncoding("ISO-8859-1"));

                xs.Serialize(xmlTextWriter, analiseConta, XMLUtils.ANSnamespace());
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                memoryStream.Position = 0;

                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(memoryStream);
                File.Copy(templatePath, filePath, true);

                XMLUtils.SubstituiCustomXmlPart(filePath, "demonstrativoAnaliseConta", xDoc);

                return filePath;
            }
            return null;
        }

        #endregion
    }
}
